<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
        <title>不规则宽高排列</title>
        <script type="text/javascript" src="jsdev/jq.dev.js">
        </script>
        <style type="text/css">
            .box {
                position: absolute;
                width: 100px;
                height: 100px;
                border: 1px solid green;
                /*margin-left: 4px;
                 margin-top: 4px;*/
            }
            
            .box2 {
                position: absolute;
                width: 100px;
                height: 202px;
                border: 1px solid green;
                /*margin-left: 4px;
                 margin-top: 4px;*/
            }
            
            .box3 {
                position: absolute;
                width: 202px;
                height: 100px;
                border: 1px solid green;
                /*margin-left: 4px;
                 margin-top: 4px;*/
            }
        </style>
    </head>
    <body>
        <!-- 排列好下面20个方块  -->
        <div id="pannel" style=" position:relative; width:600px; height:2000px; border:1px solid red; overflow:hidden;">
            <div class="box">
            </div>
            <div class="box">
            </div>
            <div class="box3">
            </div>
            <div class="box">
            </div>
            <div class="box3">
            </div>
            <div class="box">
            </div>
            <div class="box">
            </div>
            <div class="box2">
            </div>
            <div class="box">
            </div>
            <div class="box">
            </div>
            <div class="box2">
            </div>
            <div class="box">
            </div>
            <div class="box">
            </div>
            <div class="box">
            </div>
            <div class="box">
            </div>
            <div class="box2">
            </div>
            <div class="box">
            </div>
            <div class="box">
            </div>
            <div class="box">
            </div>
            <div class="box3">
            </div>
            <div class="box">
            </div>
            <div class="box">
            </div>
            <div class="box">
            </div>
            <div class="box">
            </div>
            <div class="box">
            </div>
            <div class="box">
            </div>
            <div class="box">
            </div>
            <div class="box">
            </div>
            <div class="box">
            </div>
            <div class="box2">
            </div>
            <div class="box">
            </div>
            <div class="box">
            </div>
            <div class="box">
            </div>
            <div class="box">
            </div>
            <div class="box">
            </div>
            <div class="box3">
            </div>
            <div class="box">
            </div>
            <div class="box">
            </div>
            <div class="box">
            </div>
            <div class="box3">
            </div>
            <div class="box">
            </div>
            <div class="box">
            </div>
            <div class="box">
            </div>
            <div class="box2">
            </div>
            <div class="box">
            </div>
            <div class="box2">
            </div>
            <div class="box">
            </div>
            <div class="box">
            </div>
            <div class="box">
            </div>
            <div class="box">
            </div>
        </div>
        <div id="con">
        </div>
        <script type="text/javascript">
            //初始化矩阵
            var initMatrix = function(x, y){
                if (!x || !y) {
                    return;
                }
                x = ~ ~ x;
                y = ~ ~ y;
                var mt = [];
                var i = 0;
                var getX = function(xl){
                    var i = 0;
                    var matrixX = [];
                    for (; i < xl; i++) {
                        matrixX[i] = 0;
                    }
                    return {
                        mt: matrixX,
                        isComplete: false,
                        spaces: [{
                            index: 0,
                            len: matrixX.length
                        }]
                    };
                }
                for (; i < y; i++) {
                    mt[i] = getX(x);
                    
                }
                return mt;
            }
            //生成元素相应的队列
            var getQuene = function(eleColl, base){
                if (!eleColl) {
                    return;
                }
                var quene = [];
                var i = 0;
                var len = eleColl.length;
                var getEleMatrix = function(ele, base){
                    var ht = ele.outerHeight() / base.height;
                    var wt = ele.outerWidth() / base.width;
                    return {
                        ele: ele,
                        ht: ht,
                        wt: wt
                    }
                    
                }
                for (; i < len; i++) {
                    quene[i] = getEleMatrix($(eleColl[i]), base);
                }
                return quene;
                
            }
            
            //以行为单位扫描矩阵
            var sortEveryEle = function(pannelMatrix, sortQuene){
                if (!pannelMatrix || !sortQuene) {
                    return;
                }
                var checkSpace = function(line){
                    var i = 0;
                    var len = line.mt.length;
                    var tmpWt = 0;
                    var tmpidx = 0;
                    var tmpQuene = [];
                    for (; i < len; i++) {
                        if (line.mt[i] == 0) {
                            tmpidx = i;
                            tmpWt++;
                        }
                        if ((line.mt[i] == 1) || (i == len - 1)) {
                        
                            //保存space信息到里面队列
                            if (tmpWt > 0) {
                                tmpQuene.push({
                                    index: tmpidx,
                                    len: tmpWt
                                
                                });
                            }
                            //清空临时信息
                            tmpidx = 0;
                            tmpWt = 0;
                        }
                        
                    }
                    if (tmpQuene.length > 0) {
                        line.isComplete = true;
                    }
                    line.spaces = tmpQuene;
                    return;
                }
                
                var updateMartix = function(curLine, mt, ele, spidx, lineNum){
                    var i = j = 0;
                    //获取当前空白信息
                    var sp = curLine.spaces[spidx];
                    
                    //如果占用多行则更新所有占用行的空间
                    if (ele.ht > 1) {
                        j = 0;
                        for (; j < ele.ht; j++) {
                            i = 0;
                            for (; i < ele.wt; i++) {
                                mt[lineNum + j].mt[sp.index + i] = 1;
                            }
                            //更新空白空间
                            checkSpace(mt[lineNum + j]);
                        }
                        
                    }
                    else {//如果是单行的话只要更新第一个本行
                        for (; i < ele.wt; i++) {
                            curLine.mt[sp.index + i] = 1;
                        }
                        //更新模块
                        checkSpace(curLine);
                    }
                    
                };
                var getRightEle = function(stQu, wd){
                    var i = 0;
                    var len = stQu.length;
                    for (; i < len; i++) {
                        if (stQu[i].wt <= wd) {
                            return stQu.splice(i, 1);
                            //return stQu[i].wt;
                        }
                    }
                    return;
                }
                var scanLine = function(oneLine, sortQuene, mt, lineNum){
                    var i = 0;
                    var len = oneLine.spaces.length;
                    //填充
                    for (; i < len; i++) {
                        var theWt = oneLine.spaces[i].len;
                        //判断能容纳的宽是多少
                        var rtEle = getRightEle(sortQuene, theWt);
                        if (rtEle) {
                            //放置元素
                            rtEle[0].left = oneLine.spaces[i].index * 102;//base width
                            rtEle[0].top = lineNum * 102;//base height;
                            //更新矩阵
                            updateMartix(oneLine, mt, rtEle[0], i, lineNum);
                            
                            //从sortquene中取出合适的ele，然后舍弃
                        
                            //标记已经被占有的位置
                        }
                    }
                }
                var i = j = 0;
                var pmLen = pannelMatrix.length;
                for (; i < pmLen; i++) {
                    //var todo:每次都要扫描第一行直到第一行的space 为零，isComplete为true才跳过第一行
                    scanLine(pannelMatrix[i], sortQuene, pannelMatrix, i);
                }
                
            }
            
            var con = $("#con");
            //生成相关的二维数组
            var baseWidth = 102;
            var baseHeight = 102;
            var base = {
                width: baseWidth,
                height: baseHeight
            }
            var pannel = $("#pannel");
            var thePannelSize = {
                width: pannel.width(),
                height: pannel.height()
            };
            var pannelMatrix = initMatrix(thePannelSize.width / baseWidth, thePannelSize.height / baseHeight);
            //得到要排序的不规则宽高的方块队列
            var sortQuene = getQuene(pannel.find("div"), base);
            
            //遍历matrix
            sortEveryEle(pannelMatrix, sortQuene);
        </script>
    </body>
</html>
